package com.lyubia.shop.rpc.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.lyubia.shop.api.pojo.CartVo;
import com.lyubia.shop.api.pojo.Goods;
import com.lyubia.shop.api.pojo.GoodsExample;
import com.lyubia.shop.api.service.CartService;
import com.lyubia.shop.common.exception.ParamsException;
import com.lyubia.shop.common.result.BaseResult;
import com.lyubia.shop.api.vo.CartResult;
import com.lyubia.shop.common.utils.AssertUtil;
import com.lyubia.shop.rpc.mapper.GoodsMapper;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

@Service(version = "1.0", interfaceClass = CartService.class)
public class CartServiceImpl implements CartService {

    @Resource
    private GoodsMapper goodsMapper;

    @Resource(name = "redisTemplate")
    private RedisTemplate<String, Object> redisTemplate;

    @Resource(name = "redisTemplate")
    private HashOperations<String, String, Object> hashOperations;

    @Value("${user.cartKey}")
    private String userCart;

    /**
     * 商品添加购物车
     *      1、商品参数校验
     *          商品数量大于等于1
     *      2、将商品加入购物车
     *          购物车中原本不存在
     *              put
     *          购物车中原本存在
     *              原商品数量加现商品数量
     *      3、设置商品添加时间
     *      4、返回结果
     */
    @Override
    public BaseResult saveCartVo(CartVo cartVo, Integer userId) {
        BaseResult baseResult = BaseResult.success("添加购物车成功!");
        try {
            // 校验参数
            checkCartVo(cartVo, userId);
            // 设置 redisKey
            String redisKey = userCart + ":" + userId;
            // 定义最终结果，用于存放进redis
            CartVo temp = cartVo;
            // 商品id
            Integer goodsId = cartVo.getGoodsId();
            // 使用商品id去数据库校验商品是否存在
            GoodsExample example = new GoodsExample();
            example.createCriteria().andGoodsIdEqualTo(goodsId);
            Goods good = goodsMapper.selectByExample(example).get(0);
            AssertUtil.isTrue(good == null, "商品信息不存在!");
            // 获取redis中的数据
            Map<String, Object> map = hashOperations.entries(redisKey);
            // 若购物车中存在该商品，则直接添加数量，并设置价格为数据库中的价格
            if (map.containsKey(goodsId.toString())) {
                temp = (CartVo) map.get(goodsId.toString());
                temp.setGoodsNum(temp.getGoodsNum() + cartVo.getGoodsNum());
                temp.setMarketPrice(good.getMarketPrice());
            }
            // 设置商品添加时间
            temp.setAddTime(new Date());
            // 存入redis
            hashOperations.put(redisKey, goodsId.toString(), temp);
        } catch (Exception e) {
            e.printStackTrace();
            baseResult.setCode(500);
            baseResult.setMsg(e.getMessage());
        }
        return baseResult;
    }

    /**
     * 返回购物车列表
     * @param userId 用户id
     * @return 列表
     */
    @Override
    public CartResult getCartListInfo(Integer userId) {
        CartResult cartResult = new CartResult();
        try {
            AtomicInteger i = new AtomicInteger(1);
            String redisKey = userCart + ":" + userId;
            Map<String, Object> map = hashOperations.entries(redisKey);
            if (CollUtil.isNotEmpty(map)) {
                map.forEach((key, value) -> {
                    CartVo cartVo = (CartVo) value;
                    cartResult.getCartList().add(cartVo);
                    cartResult.setTotalPrice(cartResult.getTotalPrice().add(
                            cartVo.getMarketPrice().multiply(
                                    BigDecimal.valueOf(cartVo.getGoodsNum())
                            )
                    ));
                    cartResult.setCount(cartResult.getCount()+((CartVo) value).getGoodsNum());
                });
            }
            return cartResult;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取购物车内商品数量
     * @param userId 用户id
     * @return 数量
     */
    @Override
    public Integer getCartNum(Integer userId) {
        return hashOperations.values(userCart + ":" + userId)
                .stream()
                .mapToInt(cartVo -> ((CartVo) cartVo).getGoodsNum())
                .sum();
    }

    @Override
    public BaseResult clearCart(int userId) {
        String redisKey = userCart + ":" + userId;
        Boolean i = redisTemplate.delete(redisKey);
        return i ? BaseResult.success("清空购物车成功!") : BaseResult.error("清空购物车失败!");
    }

    @Override
    public BaseResult delCartVo(Integer userId, Integer goodsId) {
        try {
            checkParam(userId, goodsId);
            String redisKey = userCart + ":" + userId;
            hashOperations.delete(redisKey, goodsId.toString());
            return BaseResult.success("删除成功!");
        } catch (Exception e) {
            e.printStackTrace();
            return BaseResult.error("删除失败!");
        }
    }

    @Override
    public BaseResult updateCartVo(Integer userId, Integer goodsId, Integer num) {
        return null;
    }

    /**
     * 校验参数
     * @param userId 用户id
     * @param goodsId 商品id
     */
    private void checkParam(Integer userId, Integer goodsId) {
        AssertUtil.isTrue(userId == null || userId == 0, "请先登录!");
        AssertUtil.isTrue(goodsId == null || goodsId == 0, "商品不存在!");
        GoodsExample example = new GoodsExample();
        example.createCriteria().andGoodsIdEqualTo(goodsId);
        List<Goods> goodsList = goodsMapper.selectByExample(example);
        if (CollUtil.isEmpty(goodsList))
            throw new ParamsException("商品不存在!");
    }

    /**
     * 参数校验
     * @param cartVo 商品信息
     */
    private void checkCartVo(CartVo cartVo, Integer userId) {
        AssertUtil.isTrue(cartVo==null, "商品信息不存在!");
        AssertUtil.isTrue(cartVo.getGoodsId() == null || cartVo.getGoodsId() < 1,"商品信息不存在!");
        AssertUtil.isTrue(cartVo.getGoodsNum() < 1, "至少添加一件商品!");
        AssertUtil.isTrue(userId==null, "请先登录!");
    }
}
